bitkeeper revision 1.1726 (42b7f1bfzMUFLRiUR9wWkzc2mh-Ing)
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Tue, 21 Jun 2005 10:53:51 +0000 (10:53 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Tue, 21 Jun 2005 10:53:51 +0000 (10:53 +0000)
Add new control messages for vcpu hotplug events.  Via the
xm vcpu-hotplug sub-program, vcpus in domains can be enabled/disabled
when CONFIG_HOTPLUG_CPU is enabled in the target domain's kernel.
Signed-off-by: Ryan Harper <ryanh@us.ibm.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c
tools/python/xen/lowlevel/xu/xu.c
tools/python/xen/xend/XendClient.py
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/server/SrvDomain.py
tools/python/xen/xend/server/messages.py
tools/python/xen/xm/main.py
xen/include/public/io/domain_controller.h

index 93952385329c53c0142f40609263b3d15d5facc6..14342b66de30983822e9bfbde36f71313b9128b4 100644 (file)
@@ -1303,6 +1303,14 @@ void __devinit smp_prepare_boot_cpu(void)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
+#include <asm-xen/ctrl_if.h>
+
+/* hotplug down/up funtion pointer and target vcpu */
+struct vcpu_hotplug_handler_t {
+       void (*fn)();
+       u32 vcpu;
+};
+static struct vcpu_hotplug_handler_t vcpu_hotplug_handler;
 
 /* must be called with the cpucontrol mutex held */
 static int __devinit cpu_enable(unsigned int cpu)
@@ -1374,6 +1382,78 @@ void __cpu_die(unsigned int cpu)
        }
        printk(KERN_ERR "CPU %u didn't die...\n", cpu);
 }
+
+static int vcpu_hotplug_cpu_process(void *unused)
+{
+       struct vcpu_hotplug_handler_t *handler = &vcpu_hotplug_handler;
+
+       if (handler->fn) {
+               (*(handler->fn))(handler->vcpu);
+               handler->fn = NULL;
+       }
+       return 0;
+}
+
+static void __vcpu_hotplug_handler(void *unused)
+{
+       int err;
+
+       err = kernel_thread(vcpu_hotplug_cpu_process, 
+                           NULL, CLONE_FS | CLONE_FILES);
+       if (err < 0)
+               printk(KERN_ALERT "Error creating hotplug_cpu process!\n");
+
+}
+
+static void vcpu_hotplug_event_handler(ctrl_msg_t *msg, unsigned long id)
+{
+       static DECLARE_WORK(vcpu_hotplug_work, __vcpu_hotplug_handler, NULL);
+       vcpu_hotplug_t *req = (vcpu_hotplug_t *)&msg->msg[0];
+       struct vcpu_hotplug_handler_t *handler = &vcpu_hotplug_handler;
+       ssize_t ret;
+
+       if (msg->length != sizeof(vcpu_hotplug_t))
+               goto parse_error;
+
+       /* grab target vcpu from msg */
+       handler->vcpu = req->vcpu;
+
+       /* determine which function to call based on msg subtype */
+       switch (msg->subtype) {
+        case CMSG_VCPU_HOTPLUG_OFF:
+               handler->fn = (void *)&cpu_down;
+               ret = schedule_work(&vcpu_hotplug_work);
+               req->status = (u32) ret;
+               break;
+        case CMSG_VCPU_HOTPLUG_ON:
+               handler->fn = (void *)&cpu_up;
+               ret = schedule_work(&vcpu_hotplug_work);
+               req->status = (u32) ret;
+               break;
+        default:
+               goto parse_error;
+       }
+
+       ctrl_if_send_response(msg);
+       return;
+ parse_error:
+       msg->length = 0;
+       ctrl_if_send_response(msg);
+}
+
+static int __init setup_vcpu_hotplug_event(void)
+{
+       struct vcpu_hotplug_handler_t *handler = &vcpu_hotplug_handler;
+
+       handler->fn = NULL;
+       ctrl_if_register_receiver(CMSG_VCPU_HOTPLUG,
+                                 vcpu_hotplug_event_handler, 0);
+
+       return 0;
+}
+
+__initcall(setup_vcpu_hotplug_event);
+
 #else /* ... !CONFIG_HOTPLUG_CPU */
 int __cpu_disable(void)
 {
index cd616e75bc492ab7440c469676008d50af4477a8..621de6272b565f223a27ec6f72d90e3ddc32309c 100644 (file)
@@ -744,6 +744,14 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
         C2P(mem_request_t, target, Int, Long);
         C2P(mem_request_t, status, Int, Long);
         return dict;
+    case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF):
+        C2P(vcpu_hotplug_t, vcpu, Int, Long);
+        C2P(vcpu_hotplug_t, status, Int, Long);
+        return dict;
+    case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON):
+        C2P(vcpu_hotplug_t, vcpu, Int, Long);
+        C2P(vcpu_hotplug_t, status, Int, Long);
+        return dict;
     }
 
     return PyString_FromStringAndSize((char *)xum->msg.msg, xum->msg.length);
@@ -909,6 +917,14 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args)
     case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
         P2C(mem_request_t, target, u32);
         break;
+    case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF):
+        P2C(vcpu_hotplug_t, vcpu, u32);
+        P2C(vcpu_hotplug_t, status, u32);
+        break;
+    case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON):
+        P2C(vcpu_hotplug_t, vcpu, u32);
+        P2C(vcpu_hotplug_t, status, u32);
+        break;
     case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
         P2C(usbif_fe_interface_status_changed_t, status, u32);
         P2C(usbif_fe_interface_status_changed_t, evtchn, u16);
index 012a8b8dcc6aec9713f2c1cc96c90bb3dda7b30a..24812f4abbd4e5425940c2d4cec1281456683b71 100644 (file)
@@ -271,6 +271,12 @@ class Xend:
                              'target'    : mem_target })
         return val
 
+    def xend_domain_vcpu_hotplug(self, id, vcpu, state):
+        return self.xendPost(self.domainurl(id),
+                            {'op'         : 'vcpu_hotplug',
+                             'vcpu'       : vcpu,
+                             'state'      : state })
+
     def xend_domain_vif_limit(self, id, vif, credit, period):
         return self.xendPost(self.domainurl(id),
                             { 'op'      : 'vif_limit_set',
index ff688f6df17d96e41c25bbb228b655b59de5b493..3944b8578d742d876d943f13dc379ceab8f27af9 100644 (file)
@@ -710,6 +710,18 @@ class XendDomain:
         dominfo = self.domain_lookup(id)
         return dominfo.mem_target_set(mem)
 
+    def domain_vcpu_hotplug(self, id, vcpu, state):
+        """Enable or disable VCPU vcpu in DOM id
+
+        @param id: domain
+        @param vcpu: target VCPU in domain
+        @param state: which state VCPU will become
+        @return: 0 on success, -1 on error
+        """
+
+        dominfo = self.domain_lookup(id)
+        return dominfo.vcpu_hotplug(vcpu, state)
+
     def domain_dumpcore(self, id):
         """Save a core dump for a crashed domain.
 
index 0383b9c9812972cb428174c0679e0880a8b7ebdf..556050d3bfe539d9c61a8e2f94edb44759bb2278 100644 (file)
@@ -956,6 +956,18 @@ class XendDomainInfo:
             msg = messages.packMsg('mem_request_t', { 'target' : target * (1 << 8)} )
             self.channel.writeRequest(msg)
 
+    def vcpu_hotplug(self, vcpu, state):
+        """Disable or enable VCPU in domain.
+        """
+        log.error("Holly Shit! %d %d\n" % (vcpu, state))
+        if self.channel:
+            if int(state) == 0:
+                msg = messages.packMsg('vcpu_hotplug_off_t', { 'vcpu' : vcpu} )
+            else:
+                msg = messages.packMsg('vcpu_hotplug_on_t',  { 'vcpu' : vcpu} )
+
+            self.channel.writeRequest(msg)
+
     def shutdown(self, reason, key=0):
         msgtype = shutdown_messages.get(reason)
         if not msgtype:
index 255e6157bf33cb747c39d2dd6cd3885e0df0ab35..fc8fd4420b608e619f7f7945e75a4ec21ab1e577 100644 (file)
@@ -180,6 +180,14 @@ class SrvDomain(SrvDir):
         val = fn(req.args, {'dom': self.dom.id})
         return val
 
+    def op_vcpu_hotplug(self, op, req):
+        fn = FormFn(self.xd.domain_vcpu_hotplug,
+                    [['dom', 'int'],
+                     ['vcpu', 'int'],
+                     ['state', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
     def render_POST(self, req):
         return self.perform(req)
         
index 0cea725e3cdba1674a7119db482dbe29d88be3c0..84fc738e686efe2111b2ff77dc1c3db1f6616bba 100644 (file)
@@ -308,6 +308,24 @@ mem_request_formats = {
 
 msg_formats.update(mem_request_formats)
 
+#============================================================================
+# Domain vcpu hotplug message.
+#============================================================================
+
+CMSG_VCPU_HOTPLUG     = 10
+CMSG_VCPU_HOTPLUG_OFF = 0
+CMSG_VCPU_HOTPLUG_ON  = 1
+
+vcpu_hotplug_formats = {
+    'vcpu_hotplug_off_t':
+    (CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF),
+
+    'vcpu_hotplug_on_t':
+    (CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON)
+    }
+
+msg_formats.update(vcpu_hotplug_formats)
+
 #============================================================================
 class Msg:
     pass
index 64716082b5783e7cc87fe55ca15867e435298c92..bcc3ded27441c15e3854750049518d79a824454b 100644 (file)
@@ -410,7 +410,8 @@ class ProgList(Prog):
         print 'Name              Id  VCPU  CPU  CPUMAP'
         for dom in doms:
             info = server.xend_domain(dom)
-            vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '?').replace('-','')
+            # XXX this is quite broken for cpu's > 9
+            vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '?').replace('-1','#')
             cpumap = sxp.child_value(info, 'cpumap', [])
             mask = ((int(sxp.child_value(info, 'vcpus', '0')))**2) - 1
             count = 0
@@ -419,7 +420,10 @@ class ProgList(Prog):
                 d['name']   = sxp.child_value(info, 'name', '??')
                 d['dom']    = int(sxp.child_value(info, 'id', '-1'))
                 d['vcpu']   = int(count)
-                d['cpu']    = int(cpu)
+                if cpu == "#":
+                    d['cpu']    = int("-1")
+                else:
+                    d['cpu']    = int(cpu)
                 d['cpumap'] = int(cpumap[count])&mask
                 count = count + 1
                 print ("%(name)-16s %(dom)3d  %(vcpu)4d  %(cpu)3d  0x%(cpumap)x" % d)
@@ -572,6 +576,35 @@ MEMORY_TARGET megabytes"""
 
 xm.prog(ProgBalloon)
 
+class ProgVcpuhotplug(Prog):
+    group = 'domain'
+    name  = 'vcpu-hotplug'
+    info  = """Enable or disable a VCPU in a domain."""
+
+    def help(self, args):
+        print args[0], "DOM VCPU [0|1]"
+        print """\nRequest virtual processor VCPU to be disabled or enabled in
+domain DOM"""
+
+    def main(self, args):
+        if len(args) != 4: self.err("%s: Invalid arguments(s)" % args[0])
+        name = args[1]
+        vcpu = int(args[2])
+        state = int(args[3])
+        dom = server.xend_domain(name)
+        id = sxp.child_value(dom, 'id')
+        vcpu_to_cpu = sxp.child_value(dom, 'vcpu_to_cpu', '-1')
+        # only send state change if states differ 
+        try:
+            # (down going up) or (up going down)
+            if (vcpu_to_cpu[vcpu] == "-1" and state == 1) or \
+               (vcpu_to_cpu[vcpu] != "-1" and state == 0):
+                server.xend_domain_vcpu_hotplug(id, vcpu, state)
+        except IndexError:
+            print "Invalid VCPU(%d)"%(vcpu)
+
+xm.prog(ProgVcpuhotplug)
+
 class ProgDomid(Prog):
     group = 'domain'
     name = 'domid'
index 69a8359aa99d87ffe1e0c6b299e1b30bd134fb22..140bff4881e395eb3403973a0ef7f91dcbc34a12 100644 (file)
@@ -61,6 +61,7 @@ typedef struct {
 #define CMSG_MEM_REQUEST    7  /* Memory reservation reqs */
 #define CMSG_USBIF_BE       8  /* USB controller backend  */
 #define CMSG_USBIF_FE       9  /* USB controller frontend */
+#define CMSG_VCPU_HOTPLUG  10  /* Hotplug VCPU messages   */
 
 /******************************************************************************
  * CONSOLE DEFINITIONS
@@ -757,6 +758,25 @@ typedef struct {
     char __pad[3]; /* 1: */
 } PACKED shutdown_sysrq_t; /* 4 bytes */
 
+/******************************************************************************
+ * VCPU HOTPLUG CONTROLS
+ */
+
+/*
+ * Subtypes for shutdown messages.
+ */
+#define CMSG_VCPU_HOTPLUG_OFF   0   /* turn vcpu off */
+#define CMSG_VCPU_HOTPLUG_ON    1   /* turn vcpu on  */
+
+/*
+ * CMSG_VCPU_HOTPLUG:
+ *  Indicate which vcpu's state should change
+ */
+typedef struct {
+    u32 vcpu;         /* 0: VCPU's whose state will change */
+    u32 status;       /* 4: Return code indicates success or failure. */
+} PACKED vcpu_hotplug_t;
+
 /******************************************************************************
  * MEMORY CONTROLS
  */